﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Reflection;
using System.Data;
using System.IO;
using System.ServiceModel.Web;
using System.Runtime.Serialization.Json;
using System.Web.Script.Serialization;

namespace SFast
{
    public static class CollectionExtensions
    {


        #region 扩展函数：   _ToList()                //DataTable 转换为List 集合
        /// <summary>
        /// DataTable 转换为List 集合
        /// </summary>
        /// <typeparam name="TResult">类型</typeparam>
        /// <param name="dt">DataTable</param>
        /// <returns></returns>
        public static IEnumerable<TResult> _ToList<TResult>(this DataTable dt) where TResult : class,new()
        {

            //创建一个属性的列表

            List<PropertyInfo> prlist = new List<PropertyInfo>();

            //获取TResult的类型实例 反射的入口

            Type t = typeof(TResult);

            //获得TResult 的所有的Public 属性 并找出TResult属性和DataTable的列名称相同的属性(PropertyInfo) 并加入到属性列表

            Array.ForEach<PropertyInfo>(t.GetProperties(), p => { if (dt.Columns.IndexOf(p.Name) != -1) prlist.Add(p); });

            //创建返回的集合
            List<TResult> oblist = new List<TResult>();

            foreach (DataRow row in dt.Rows)
            {

                //创建TResult的实例

                TResult ob = new TResult();

                //找到对应的数据 并赋值

                prlist.ForEach(p =>
                {
                    if (row[p.Name] != DBNull.Value)
                    {
                        p.SetValue(ob, Convert.ChangeType(row[p.Name], Nullable.GetUnderlyingType(p.PropertyType) ?? p.PropertyType), null);
                    }
                });

                //放入到返回的集合中.

                oblist.Add(ob);

            }

            return oblist;
        }
        #endregion

        #region 扩展函数：   _ToDataTable()           //List转换为DataTable
        /// <summary>
        /// 转换为一个DataTable
        /// </summary>
        /// <typeparam name="TResult">IEnumerable对象</typeparam>
        /// <param name="value">DataTable对象</param>
        /// <returns></returns>
        public static DataTable _ToDataTable<TResult>(this IEnumerable<TResult> value) where TResult : class
        {

            //创建属性的集合

            List<PropertyInfo> pList = new List<PropertyInfo>();

            //获得反射的入口

            Type type = typeof(TResult);

            DataTable dt = new DataTable();

            //把所有的public属性加入到集合 并添加DataTable的列

            Array.ForEach<PropertyInfo>(type.GetProperties(), p =>
            {
                pList.Add(p);
                Type cotype = p.PropertyType;
                if (cotype.IsGenericType && (cotype.GetGenericTypeDefinition() == typeof(Nullable<>)))
                {
                    cotype = cotype.GetGenericArguments()[0];
                }
                dt.Columns.Add(p.Name, cotype);
            });

            foreach (var item in value)
            {

                //创建一个DataRow实例

                DataRow row = dt.NewRow();

                //给row 赋值

                pList.ForEach(p => row[p.Name] = p.GetValue(item, null) == null ? DBNull.Value.ToString() : p.GetValue(item, null));

                //加入到DataTable

                dt.Rows.Add(row);

            }

            return dt;
        }
        #endregion

        #region 扩展函数：   _ToJsonObj（）  // 对象转换为Json格式字符串
        /// <summary>
        /// Json格式的字符串转换为对象
        /// </summary>
        /// <typeparam name="T">Object对象</typeparam>
        /// <param name="jsonString">Json格式的字符串</param>
        /// <returns></returns>
        public static T _ToJsonObj<T>(this string jsonString) where T : new()
        {
            if (String.IsNullOrEmpty(jsonString))
            {
                return default(T);
            }
            return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(jsonString);
        }
        #endregion

        #region 扩展函数：   _ToJsonStr（）  //对象转换为Json格式字符串
        /// <summary>
        /// 对象转换为Json格式字符串
        /// </summary>
        /// <typeparam name="T">类型<peparam>
        /// <param name="list">泛型集合</param>
        /// <returns></returns>
        public static string _ToJsonStr(this Object list)
        {
            return Newtonsoft.Json.JsonConvert.SerializeObject(list, Newtonsoft.Json.Formatting.None);
            //JavaScriptSerializer serializer = new JavaScriptSerializer();
            //return serializer.Serialize(list);


        }
        #endregion

        #region 扩展函数：   _ToCSV（）  把集合用指定字符分割
        /// <summary>
        ///  把集合用指定字符分割
        /// </summary>
        /// <typeparam name="T">集合中单一项的类：如：String、int</typeparam>
        /// <param name="collection">当前集合</param>
        /// <param name="delim">指定用于分隔的字符串</param>
        /// <returns>返回分隔后的字符串</returns>
        public static string _ToCSV<T>(this IEnumerable<T> collection, string delim)
        {
            if (collection == null)
            {
                return "";
            }

            StringBuilder result = new StringBuilder();
            foreach (T value in collection)
            {
                result.Append(value);
                result.Append(delim);
            }
            if (result.Length > 0)
            {
                result.Length -= delim.Length;
            }
            return result.ToString();
        }
        #endregion

        #region 把byte[]转换成16进制的字符串
        /// <summary>
        /// 把byte[]转换成16进制的字符串
        /// </summary>
        /// <param name="bytes">要转换的byte[]</param>
        /// <returns></returns>
        public static String _ToHaxString(this Byte[] bytes)
        {
            if (bytes == null)
            {
                throw new NullReferenceException("参数nytes不可为空!");
            }
            StringBuilder rsu = new StringBuilder();
            foreach (byte b in bytes)
            {
                var str = Convert.ToString(b, 16);
                if (str.Length < 2)
                {
                    str = "0" + str;
                }
                rsu.Append(str);
            }
            return rsu.ToString();
        }
        #endregion

        #region
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="item1"></param>
        /// <param name="item2"></param>
        /// <param name="items"></param>
        /// <returns></returns>
        public static T[] Combine<T>(this T item1, T item2, params T[] items)
        {
            if (item1 == null && item2 == null)
                throw new ArgumentNullException("item1 and item2");

            if (item1 == null)
                return Combine<T>(item2, items);

            if (item2 == null)
                return Combine<T>(item1, items);

            //if we reached here then item1 and item2 are not null
            if (items == null)
            {
                return new T[2] { item1, item2 };
            }
            else
            {
                T[] combination = new T[items.Length + 2];
                combination[0] = item1;
                combination[1] = item2;
                for (int i = 2; i < combination.Length; i++)
                {
                    combination[i] = items[i - 2];
                }
                return combination;
            }
        }
        /// <summary>
        /// combination helper method
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="item"></param>
        /// <param name="items"></param>
        /// <returns></returns>
        public static T[] Combine<T>(this T item, params T[] items)
        {
            if (items == null)
            {
                return new T[1] { item };
            }
            else
            {
                T[] combination = new T[items.Length + 1];
                combination[0] = item;
                for (int i = 1; i < combination.Length; i++)
                {
                    combination[i] = items[i - 1];
                }
                return combination;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="queryable"></param>
        /// <returns></returns>
        public static bool Exists<T>(this IQueryable<T> queryable)
        {
            return queryable.Count() != 0;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="coll"></param>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public static bool TrueForAll<T>(this IEnumerable<T> coll, Predicate<T> predicate)
        {
            Trace.Assert(coll != null, "coll == hhhhhhhh");
            Trace.Assert(predicate != null, "predicate == null");

            using (var it = coll.GetEnumerator())
                while (it.MoveNext())
                {
                    if (!predicate(it.Current))
                        return false;
                }

            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="coll"></param>
        /// <param name="action"></param>
        public static void ForEach<T>(this IEnumerable<T> coll, Action<T> action)
        {
            Trace.Assert(coll != null, "coll == null");
            Trace.Assert(action != null, "action == null");

            var it = coll.GetEnumerator();
            while (it.MoveNext())
                action(it.Current);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TInput"></typeparam>
        /// <typeparam name="TOutput"></typeparam>
        /// <param name="coll"></param>
        /// <param name="converter"></param>
        /// <returns></returns>
        public static IEnumerable<TOutput> ConvertAll<TInput, TOutput>(this IEnumerable<TInput> coll, Converter<TInput, TOutput> converter)
        {
            Trace.Assert(coll != null, "coll == null");
            Trace.Assert(converter != null, "converter == null");

            return from input in coll
                   select converter(input);
        }


        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="coll"></param>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public static bool Exist<T>(this IEnumerable<T> coll, Predicate<T> predicate)
        {
            Trace.Assert(coll != null, "coll == null");
            Trace.Assert(predicate != null, "predicate == null");

            var it = coll.GetEnumerator();
            while (it.MoveNext())
                if (predicate(it.Current))
                    return true;

            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <param name="c"></param>
        /// <returns></returns>
        public static bool In<T>(this T t, IEnumerable<T> c)
        {
            return c.Any(i => i.Equals(t));
        }

        //public static T[] _<T>(this T item)
        //{
            
            
        //    return ;
        //}
        #endregion

        


    }
}
